
/*
    hooks：
        useState
*/
import { useState } from "react"
function TestTwo() {
    // useState 返回一个数组，第一个元素是当前状态，第二个元素是更新状态的函数
    // useState 接受一个参数，这个参数是初始状态
    // useState 包裹的变量是响应式的，当状态改变时，组件会重新渲染
    const [str, setStr] = useState('test')
    // const [str, setStr] = useState<string>('test')

    const [bool, setBool] = useState(false)
    // const [bool, setBool] = useState<boolean>(false)

    const handleClick = () => {
        setStr('test2')    // dom更新了，说明这时异步任务， 做成异步，是为了避免频繁更新dom，提高性能
        console.log(str);  // 值没变，  这时同步任务
    }

    const handleClick2 = () => {
        setBool(!bool)
    }

    // 复杂类型
    const [arr, setArr] = useState([1, 2, 3])

    const handleClick3 = () => {
        // arr.push(4)        // 不能操作原数组，无效
        console.log(arr);  // 值变了，dom没有更新
        // 使用setArr更新状态，会触发组件重新渲染
        setArr([...arr, 4])
        setArr(arr.filter((item) => item !== 3))  // 可以使用filter、map、slice等会生成新数组的方法
        setArr([
            ...arr.slice(0, 2),
            99,
            ...arr.slice(3)
        ])  
    }

    // 对象
    const [obj, setObj] = useState(() => {
        // 可以放函数，但一定要有返回值，返回值就是初始状态
        // 函数里可以放一些复杂的逻辑，但只能初始化执行一次
        return {
            name: 'lili',
            age: 18
        }
    })
    const handleClick4 = () => {
        // obj.name = 'test2'  // 不能直接修改对象，无效
        // setObj(obj)         // 不能直接修改对象，无效
        // setObj(Object.assign({}, obj, { name: 'test2' }))  // 可以使用Object.assign，老的方式
        setObj({
            ...obj,
            name: 'zhangsan'
        })
    }

    // console.log('组件渲染');
    const [num, setNum] = useState(0)
    const handleClick5 = () => {
        // setNum(1)
        // setNum(2)
        // setNum(3)   // 只会渲染一次，最后一个，因为setNum是异步的，节省性能
        
        // setNum(num + 1)
        // setNum(num + 1)
        // setNum(num + 1)   
        // 上面三个setNum，加了3次，但结果页面上显示 1
        // 是因为三个setNum执行同一个操作，最终只会执行一次，自带防抖效果，异步任务，会走队列，当发现执行了一次，后面的相同操作会被阻断
        // 解决办法，使用函数式更新
        setNum((num) => num + 1)
        setNum((num) => num + 1)
        setNum((num) => num + 1)
    }

    return (
        <>
            <h1>{str}</h1>
            <button onClick={handleClick}>更改</button>
            <h1>{bool ? 'show':'hide'}</h1>
            <button onClick={handleClick2}>更改</button>

            <h1>{arr}</h1>
            <button onClick={handleClick3}>更改数组</button>

            <h1>{obj.name}</h1>
            <h1>{obj.age}</h1>
            <button onClick={handleClick4}>更改对象</button>

            <h1>{num}</h1>
            <button onClick={handleClick5}>更改</button>
        </>
    )
}

export default TestTwo